﻿using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using PublicTransportEnabler.net.Contract;
using PublicTransportEnabler.net.Web;

namespace PublicTransportEnabler.net.Util
{
    public class ParserUtils : IParserUtils
    {
        private string SCRAPE_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0";
        private string SCRAPE_ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        private int SCRAPE_INITIAL_CAPACITY = 4096;
        private int SCRAPE_CONNECT_TIMEOUT = 5000;
        private int SCRAPE_READ_TIMEOUT = 15000;
        private string SCRAPE_DEFAULT_ENCODING = "ISO-8859-1";
        private int SCRAPE_PAGE_EMPTY_THRESHOLD = 2;
        private Regex P_REFRESH = new Regex("<META\\s+http-equiv=\"refresh\"\\s+content=\"\\d+;\\s*URL=([^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        private string stateCookie;

        public void ResetState()
        {
            stateCookie = null;
        }

        public string Scrape(string url)
        {
            return Scrape(url, null, null, null);
        }

        public string Scrape(string url, string postRequest, string encoding, string sessionCookieName)
        {
            return Scrape(url, postRequest, encoding, sessionCookieName, 3);
        }

        public string Scrape(string urlStr, string postRequest, string encoding, string sessionCookieName, int tries)
        {
            return Scrape(urlStr, postRequest, encoding, sessionCookieName, null, 3);
        }

        public string Scrape(string urlStr, string postRequest, string encoding, string sessionCookieName, string httpReferrer, int tries)
        {
            if (encoding == null)
                encoding = SCRAPE_DEFAULT_ENCODING;

            Encoding transportEncoding = Encoding.GetEncoding(encoding);
            WebClient client = new GzipWebClient { Encoding = transportEncoding };


            //URL url = new URL(urlStr);

            client.Headers.Add(HttpRequestHeader.UserAgent, SCRAPE_USER_AGENT);
            client.Headers.Add(HttpRequestHeader.Accept, SCRAPE_ACCEPT);
            client.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
            client.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");

            if (!string.IsNullOrWhiteSpace(httpReferrer))
                client.Headers.Add(HttpRequestHeader.Referer, httpReferrer);

            if (sessionCookieName != null && stateCookie != null)
                client.Headers.Add(HttpRequestHeader.Cookie, stateCookie);



            string response = null;

            if (postRequest != null)
            {
                byte[] postRequestBytes = transportEncoding.GetBytes(postRequest);



                client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                client.Headers.Add("Content-Length", postRequestBytes.Length.ToString(CultureInfo.InvariantCulture));

                byte[] responseArray = client.UploadData(urlStr, "POST", postRequestBytes);

                response = transportEncoding.GetString(responseArray);
            }
            else
            {
                response = client.DownloadString(urlStr);
            }

            Encoding iso = Encoding.GetEncoding("Windows-1252");
            Encoding utf8 = Encoding.UTF8;

            
            byte[] isoBytes = iso.GetBytes(response);
            byte[] utfBytes = Encoding.Convert(iso, utf8, isoBytes);

            string msg = utf8.GetString(utfBytes);

            return msg;

        }

        private Regex P_ENTITY = new Regex("&(?:#(x[\\da-f]+|\\d+)|(amp|quot|apos|szlig|nbsp));", RegexOptions.Compiled);

        public string ResolveEntities(string str)
        {
            if (str == null)
                return null;

            Match matcher = P_ENTITY.Match(str);
            StringBuilder builder = new StringBuilder(str.Length);
            //int pos = 0;
            //while (matcher.Success)
            //{
            //     char c;
            //     string code = matcher.Groups[1].Value;
            //    if (code != null)
            //    {
            //        if (code[0] == 'x')
            //            c = (char) Integer.valueOf(code.substring(1), 16).intValue();
            //        else
            //            c = (char) Integer.parseInt(code);
            //    }
            //    else
            //    {
            //         string namedEntity = matcher.group(2);
            //        if (namedEntity.equals("amp"))
            //            c = '&';
            //        else if (namedEntity.equals("quot"))
            //            c = '"';
            //        else if (namedEntity.equals("apos"))
            //            c = '\'';
            //        else if (namedEntity.equals("szlig"))
            //            c = '\u00df';
            //        else if (namedEntity.equals("nbsp"))
            //            c = ' ';
            //        else
            //            throw new IllegalStateException("unknown entity: " + namedEntity);
            //    }
            //    builder.append(str.subSequence(pos, matcher.start()));
            //    builder.append(c);
            //    pos = matcher.end();
            //}
            //builder.append(str.subSequence(pos, str.length()));
            return builder.ToString();
        }

        public string UrlEncode(string str)
        {
            return System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8);
        }

        public string UrlEncode(string str, string encoding)
        {
            return System.Web.HttpUtility.UrlEncode(str, Encoding.GetEncoding(encoding));
        }


        public string UrlDecode(string str, string encoding)
        {
            return System.Web.HttpUtility.UrlDecode(str, Encoding.GetEncoding(encoding));
        }

        public string P_PLATFORM = "[\\wÄÖÜäöüßáàâéèêíìîóòôúùû\\. -/&#;]+?";
    }
}